﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;

public enum TroopState
{
    Free, //单位个体自由行动，部队不对其下达命令
    FormationMoving, //所有单位以阵型移动
    Fighting, //所有单位加入战斗之中
    RangeAttacking, //所有单位持续发动远程攻击
}


public class TroopLeader : BattleComponent<TroopLeader> {
    
    Ticker leaderAiUpdateTicker = new Ticker(5, true);


    public Transform troopCenter;
    public TroopFormationPivot formationPivot;
    public TroopVehicle vehicle;
    public TroopWarrior warrior;
    public int initarmyCount; //初始的士兵数量
    public WarFlagOrigin warFlgOrigin;
    public PlayerType troopOwner;

    public bool isPlayer; //是否由玩家操控
    public GameObject unitPrefab;

    public float leader2CenterMaxDistance;

    public Timer timer;

    public TroopState troopState;
    public Vector3 centerPosition; //部队中心点



    public float fightRatio; //部队中陷入近战的比率，比率大于一定程度时就会停止移动
    public int unitCount;

    public float avgSpeed;

    List<Formation.FormationUnit> fuList = new List<Formation.FormationUnit>();

    public bool toDestroy;

    private void Start()
    {
        InitArmy();
        timer = new Timer(float.MaxValue);
    }

    private void OnEnable()
    {
        Assign(this);
        TroopLeaderManager.Instance.Enroll(this);
    }

    private void OnDisable()
    {
        Unassign(this);
        TroopLeaderManager.Instance.Disenroll(this);
    }

    public void InitArmy()
    {
        for (int i = 0; i < initarmyCount; i++)
        {
            GameObject g;
            g = Instantiate(unitPrefab, transform.position , new Quaternion());
            Formation.FormationUnit fu = new Formation.FormationUnit(g.GetComponent<SoldierAI>(), "inf");
            fuList.Add(fu);
        }
        formationPivot.formation.AssignSlot(fuList, transform);
    }

    public void ReAssignFormation()
    {
        formationPivot.formation.AssignSlot(fuList, transform);
    }








    public bool TroopHasSoldier()
    {
        return unitCount > 0;
    }

    public static void UpdateLeaderAI()
    {
        foreach(var leader in ComponentDataList)
        {
            leader.timer.Tick(Time.deltaTime);
            if(!leader.TroopHasSoldier())
            {
                leader.toDestroy = true;
                continue;
            }
            if(leader.leaderAiUpdateTicker.Tick())
            {
                leader.formationPivot.formation.UpdateArriveRatio();
                leader.UpdateState();
                leader.UpdateTroopData();
            }
        }
    }

    public static void CleanUpTroopLeaders()
    {
        int i = 0;
        while (i < ComponentDataList.Count)
        {
            if (ComponentDataList[i].toDestroy)
            {
                ComponentDataList[i].gameObject.SetActive(false);
                ComponentDataList[i].toDestroy = false;
            }
            i++;
        }
    }



    private void UpdateState()
    {
        
        switch (troopState)
        {
            case TroopState.Fighting:
                MoveAllUnitToTargetTroop();
                if (fightRatio < warrior.fihgtThresholdRatio)
                {
                    ToState(TroopState.Free);
                    break;
                }
                break;
            case TroopState.Free:
                if (fightRatio > warrior.fihgtThresholdRatio)
                {
                    ToState(TroopState.Fighting);
                    break;
                }
                if (vehicle.formationMove &&  !vehicle.isReachTarget)
                {
                    ToState(TroopState.FormationMoving);
                    break;
                }
                if (warrior.rangedAttackTarget != null && warrior.rangedAttackTarget.centerPosition.DistanceLessThan(centerPosition, warrior.rangedAttackRange))
                {
                    ToState(TroopState.RangeAttacking);
                    break;
                }
                break;
            case TroopState.FormationMoving:
                if (fightRatio > warrior.fihgtThresholdRatio)
                {
                    ToState(TroopState.Fighting);
                    break;
                }
                Debug.Log(vehicle.isReachTarget.ToString()  + formationPivot.formation.ArriveRatio.ToString());
                
                if (!vehicle.formationMove ||
                    (vehicle.isReachTarget && formationPivot.formation.ArriveRatio> formationPivot.FormationArriveThreshold)) 
                {
                    ToState(TroopState.Free);
                    break;
                }
                if (warrior.rangedAttackTarget != null && warrior.rangedAttackTarget.centerPosition.DistanceLessThan(centerPosition, warrior.rangedAttackRange))
                {
                    ToState(TroopState.RangeAttacking);
                    break;
                }
                break;
            case TroopState.RangeAttacking:
                if(timer.IsTimerFinish(warrior.UpdateRangeAttackTargetDeltaTime))
                {
                    UpdateRangeAttackTarget();
                    timer.Reset();
                }
                if (warrior.rangedAttackTarget==null || warrior.rangedAttackTarget.unitCount == 0)
                {
                    ToState(TroopState.Free);
                    break;
                }
                if (vehicle.formationMove)
                {
                    ToState(TroopState.FormationMoving);
                    break;
                }

                break;
        }
    }

    /// <summary>
    /// 更新与部队相关的统计数据，例如部队中士兵的参战率，士兵的平均位置
    /// </summary>
    private void UpdateTroopData()
    {
        Vector3 sumPos = Vector3.zero;
        float sumSpeed = 0;
        int fightUnitCount = 0;
        unitCount = 0;
        for (int i = 0; i < fuList.Count; i++)
        {
            if (fuList[i].unit!=null && !fuList[i].unit.isActiveAndEnabled)
            {
                fuList[i].unit = null;
            }

            if (fuList[i].unit != null)
            {
                if (fuList[i].unit.IsFighting) fightUnitCount++;
                unitCount++;
                sumPos += fuList[i].unit.transform.position;
                sumSpeed += fuList[i].unit.soldierVehicle.runSpeed;
            }
        }
        if (unitCount == 0) return;
        centerPosition = (1.0f / unitCount) * sumPos;
        troopCenter.transform.position = centerPosition;
        troopCenter.transform.rotation = transform.rotation;
        fightRatio = (float)fightUnitCount / unitCount;
        avgSpeed = sumSpeed / unitCount;
    }


    protected void ToState(TroopState state)
    {
        if (unitCount == 0)
        {
            return;
        }
        if (state!=troopState)
        {
            ExitState(troopState);
        }
        switch(state)
        {
            case TroopState.Fighting:
                troopState = TroopState.Fighting;
                switch(troopOwner)
                {
                    case PlayerType.Player:
                        warrior.MeleeAttackTarget = TroopLeaderManager.Instance.GetNearestTroopLeader(transform.position, PlayerType.AIEnemy);
                        break;
                    case PlayerType.AIEnemy:
                        warrior.MeleeAttackTarget = TroopLeaderManager.Instance.GetNearestTroopLeader(transform.position, PlayerType.Player);
                        break;
                }
                break;
            case TroopState.Free:
                StandThere();
                troopState = TroopState.Free;
                break;
            case TroopState.FormationMoving:
                troopState = TroopState.FormationMoving;
                //vehicle.formationMove = true;
                ReAssignFormation();
                break;
            case TroopState.RangeAttacking:
                troopState = TroopState.RangeAttacking;
                RangedAttack();
                timer.Reset();
                break;
        }
    }

    //让士兵站在原地
    protected void StandThere()
    {
        foreach(var fu in fuList)
        {
            if(fu.unit!=null)
            {
                fu.unit.desireTarget = fu.unit.transform.position;
            }
        }
    }

    protected void ExitState(TroopState state)
    {
        switch (state)
        {
            case TroopState.Fighting:
                break;
            case TroopState.Free:
                break;
            case TroopState.FormationMoving:
                vehicle.formationMove = false;
                break;
            case TroopState.RangeAttacking:
                StopRangedAttack();
                timer.Reset();
                break;
        }
    }

    protected void RangedAttack()
    {
        UpdateRangeAttackTarget();
    }

    protected void UpdateRangeAttackTarget()
    {
        if (warrior.rangedAttackTarget == null || warrior.rangedAttackTarget.unitCount == 0) return;
        List<SoldierAI> soldiers = warrior.rangedAttackTarget.GetValidSoldiers();
        Debug.Log(soldiers.Count);
        for (int i = 0; i < fuList.Count; i++)
        {
            var fu = fuList[i];
            if (fu.unit != null)
            {
                fu.unit.warrior.target = soldiers[Random.Range(0, soldiers.Count)].warrior;
                fu.unit.warrior.ToRangeAttack = true;
            }
        }
    }


    protected void StopRangedAttack()
    {
        warrior.rangedAttackTarget = null;
        for (int i = 0; i < fuList.Count; i++)
        {
            var fu = fuList[i];
            if (fu.unit != null)
            {
                fu.unit.warrior.target = null;
                fu.unit.warrior.ToRangeAttack = false;
            }
        }

    }

    public List<SoldierAI> GetValidSoldiers()
    {
        List<SoldierAI> soldiers = new List<SoldierAI>();
        foreach(var fu in fuList)
        {
            if(fu.unit!=null && fu.unit.isActiveAndEnabled)
            {
                soldiers.Add(fu.unit);
            }
        }
        return soldiers;
    }



    protected void MoveAllUnitToTargetTroop()
    {
        if(warrior.MeleeAttackTarget!=null)
        {
            foreach(var fu in fuList)
            {
                if(fu.unit!=null)
                {  
                    fu.unit.desireTarget = warrior.MeleeAttackTarget.centerPosition;
                }
            }
        }
    }


    public void ChargeTo(Vector3 target)
    {
        foreach(var fu in fuList)
        {
            if(fu.unit!=null)
            {
                fu.unit.warrior.toCharge = true;
                fu.unit.desireTarget = target;
            }
        }
    }

    








}
